﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.Web.Routing;

namespace System.Web.Mvc.Ajax
{
    /// <summary>
    /// 数字分页方式的Ajax分页控件生成类
    /// </summary>
    public class AjaxNumericPaggerFormat : AjaxPaggerFormat
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="options">AjaxHelper.AjaxOptions对象</param>
        public AjaxNumericPaggerFormat(AjaxOptions options)
            : base(options)
        {
            this.PreviousLabel = "previous";
            this.NextLabel = "next";
        }

        /// <summary>
        /// 上一页按钮Label，默认值：previous
        /// </summary>
        public string PreviousLabel { get; set; }

        /// <summary>
        /// 下一页按钮Label，默认值：next
        /// </summary>
        public string NextLabel { get; set; }

        private const int num_display_entries = 10;

        /// <summary>
        /// 生成HttpGet方式的分页控件
        /// </summary>
        /// <param name="actionName">获取分页数据的Action Name</param>
        /// <param name="controllerName">获取分页数据的Controller Name</param>
        /// <param name="routeValues">获取分页数据的路由参数</param>
        /// <param name="rowCount">分页的总行数</param>
        /// <param name="pageIndex">当前分页索引，从0开始</param>
        /// <param name="pageSize">每页显示个数</param>
        /// <returns></returns>
        public override string GenerateGetFormatString(string actionName, string controllerName, RouteValueDictionary routeValues, int rowCount, int pageIndex, int pageSize)
        {
            int pageCount = pageSize != 0 ? (rowCount % pageSize == 0 ? rowCount / pageSize : rowCount / pageSize + 1) : 0;
            if (pageCount <= 1)
            {
                return String.Empty;
            }
            UrlHelper urlHelper = new UrlHelper(this.Helper.ViewContext.RequestContext);
            string formAction = urlHelper.Action(actionName, controllerName, routeValues);
            formAction = urlHelper.Content(formAction);
            StringBuilder sb = new StringBuilder();
            Dictionary<string, object> additionalAttributes = new Dictionary<string, object>()
            {
                { "data-ajax-success", "{formId}$Paging$Callback" }
            };
            using (AjaxForm form = new AjaxForm(this.Helper, formAction, this.Options,
                additionalAttributes, sb, false))
            {
                string successCallback = this.Options.OnSuccess;

                form.BeginChild("script", new Dictionary<string, string>() {
                    { "type", "text/javascript" }
                });

                StringBuilder scripts = new StringBuilder();
                scripts.Append("function " + form.FormId + "$Paging$Callback(data, userContext, methodName) {");
                if (!String.IsNullOrEmpty(successCallback))
                {
                    scripts.Append("try { " + successCallback + "(data, userContext, methodName); }catch(e){}");
                }

                scripts.AppendFormat("_ajaxNumericPagger.generatePagger('{0}',{1},{2},'{3}','{4}');",
                    form.FormId, pageCount, num_display_entries, this.PreviousLabel, this.NextLabel);
                scripts.Append("};");

                form.AppendHtml(scripts.ToString());
                form.EndChild("script");

                form.AppendChild("input", new Dictionary<string, string>() { 
                    { "type", "hidden" }, 
                    { "name", "pageIndex" },
                    { "value", pageIndex.ToString() }
                });

                HttpRequest request = System.Web.HttpContext.Current.Request;
                if (request.Form.HasKeys())
                {
                    foreach (string key in request.Form.Keys)
                    {
                        if (key != "pageIndex")
                        {
                            form.AppendChild("input", new Dictionary<string, string>() { 
                                { "type", "hidden" }, 
                                { "name", key },
                                { "value", request[key] }
                            });
                        }
                    }
                }

                form.AppendChild("div", new Dictionary<string, string>()
                {
                    { "class", "pagger-numeric-list" }
                });
                if (pageIndex > 0)
                {
                    form.AppendChild("input", new Dictionary<string, string>() 
                    {
                        { "type", "button" },
                        { "value", this.PreviousLabel },
                        { "onclick", "$('#" + form.FormId + "').find(':hidden[name=pageIndex]:first').val('" + ( pageIndex - 1 ) + "');$('#" + form.FormId + "').submit();" }
                    });
                }

                List<int> numRange = GetRange(pageIndex, pageCount);

                if (numRange.First() > 0)
                {
                    form.AppendChild("input", new Dictionary<string, string>()
                    {
                        { "type", "button" },
                        { "value", "1" },
                        { "onclick", "$('#" + form.FormId + "').find(':hidden[name=pageIndex]:first').val('0');$('#" + form.FormId + "').submit();" }
                    });
                    form.AppendHtml("<span>...</span>");
                }

                foreach (int num in numRange)
                {
                    if (num != pageIndex)
                    {
                        form.AppendChild("input", new Dictionary<string, string>()
                        {                            
                            { "type", "button" },
                            { "value", (num + 1).ToString() },
                            { "onclick", "$('#" + form.FormId + "').find(':hidden[name=pageIndex]:first').val('" + num + "');$('#" + form.FormId + "').submit();" }
                        });
                    }
                    else
                    {
                        form.AppendHtml(String.Format("<span>{0}</span>", num + 1));
                    }
                }

                if (numRange.Last() < pageCount - 1)
                {
                    form.AppendHtml("<span>...</span>");
                    form.AppendChild("input", new Dictionary<string, string>()
                    {
                        { "type", "button" },
                        { "value", pageCount.ToString() },
                        { "onclick", "$('#" + form.FormId + "').find(':hidden[name=pageIndex]:first').val('" + (pageCount - 1) + "');$('#" + form.FormId + "').submit();" }
                    });
                }

                if (pageIndex < pageCount - 1)
                {
                    form.AppendChild("input", new Dictionary<string, string>()
                    {
                        { "type", "button" },
                        { "value", this.NextLabel },
                        { "onclick", "$('#" + form.FormId + "').find(':hidden[name=pageIndex]:first').val('" + (pageIndex + 1) + "');$('#" + form.FormId + "').submit();" }
                    });
                }

                form.EndChild("div");
            }

            return sb.ToString();
        }

        /// <summary>
        /// 生成HttpPost方式的分页控件
        /// </summary>
        /// <param name="actionName">获取分页数据的Action Name</param>
        /// <param name="controllerName">获取分页数据的Controller Name</param>
        /// <param name="routeValues">获取分页数据的路由参数</param>
        /// <param name="rowCount">分页的总行数</param>
        /// <param name="pageIndex">当前分页索引，从0开始</param>
        /// <param name="pageSize">每页显示个数</param>
        /// <returns></returns>
        public override string GeneratePostFormatString(string actionName, string controllerName, RouteValueDictionary routeValues, int rowCount, int pageIndex, int pageSize)
        {
            return GenerateGetFormatString(actionName, controllerName, routeValues, rowCount, pageIndex, pageSize);
        }

        private List<int> GetRange(int pageIndex, int pageCount)
        {
            int ne_half = (int)Math.Ceiling(num_display_entries / 2d);
            int upper_limit = pageCount - num_display_entries;
            int start = pageIndex > ne_half ? (Math.Max(Math.Min(pageIndex - ne_half, upper_limit), 0)) : 0;
            int end = pageIndex > ne_half ? Math.Min(pageIndex + ne_half, pageCount) : Math.Min(num_display_entries, pageCount);
            List<int> range = new List<int>();
            for (int i = start; i < end; i++)
            {
                range.Add(i);
            }
            return range;
        }
    }
}
